﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Raven.Client;
using BattleThis.Core;
using Raven.Client.Linq;

namespace BattleThis.RavenDB
{
	public class RavenRepository<T> : IRepository<T> where T : class 
	{

		#region Variablen
		private IDocumentSession m_Session;
		#endregion

		#region Properties

		protected bool AddedNewValues { get; set; }

		private IDocumentSession Session
		{
			get
			{
				return m_Session;
			}
		}

		#endregion

		#region Methoden
	
		public RavenRepository( IUnitOfWork unitOfWork )
		{
			if( !( unitOfWork is RavenUnitOfWork ) )
			{
				throw new InvalidOperationException( "Invalid Type" );
			}

			m_Session = ( (RavenUnitOfWork)unitOfWork ).Session;
		}

		private RavenRepository( IDocumentSession session )
		{
			if( session == null ) throw new ArgumentNullException( "session" );

			m_Session = session;
		}

		public IEnumerable<T> GetAll()
		{
			return this.Query().ToList();
		}

		public IEnumerable<T> Find( Func<T, bool> where )
		{
			return this.Query().Where<T>( where );
		}

		public T Single( Func<T, bool> where )
		{
			return this.Query().SingleOrDefault<T>( where );
		}

		public T First( Func<T, bool> where )
		{
			return this.Query().First<T>( where );
		}

		public virtual void Delete( T entity )
		{
			this.Session.Delete( entity );
		}

		public virtual void Add( T entity )
		{
			this.Session.Store( entity );
		}

		public void SaveChanges()
		{
			this.Session.SaveChanges();
			this.Session.Advanced.Clear();
		}

		/// <summary>
		/// Queries this instance and ensure new data will be recognized.
		/// </summary>
		/// <returns>
		/// See http://stackoverflow.com/questions/9411804/is-embedded-ravendb-and-mvc-possible/9411934#comment11899078_9411934
		/// </returns>
		protected IRavenQueryable<T> Query()
		{
			return this.Session.Query<T>().Customize( x => x.WaitForNonStaleResultsAsOfLastWrite() );
		}

		#endregion

	}
}
